home *** CD-ROM | disk | FTP | other *** search
/ Precision Software Appli…tions Silver Collection 1 / Precision Software Applications Silver Collection Volume One (PSM) (1993).iso / tutor / cptutt22.arj / CHAP04.TXT < prev    next >
Text File  |  1992-01-20  |  22KB  |  472 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.                                                         Chapter 4
  8.                                                         FUNCTIONS
  9.  
  10. This chapter discusses enhancements in the capabilities of
  11. functions that have been made to C++.  These changes make
  12. programming more convenient and permit the compiler to do further
  13. checking for errors.  A fair amount of time is also spent in this
  14. chapter teaching the modern form of function definition and
  15. prototyping.
  16.  
  17. Prototyping allows the compiler to do additional type checking for
  18. your function calls which can detect some programming errors.  The
  19. first two example programs in this chapter are designed to teach
  20. prototyping and what it will do for you.  Prototyping is a
  21. relatively new addition to C, so even some experienced C
  22. programmers are not familiar with it.  If you have experience with
  23. prototyping you can skip directly to the section named PASS BY
  24. REFERENCE on page 4-4 of this chapter.
  25.  
  26.  
  27. PROTOTYPES
  28. _________________________________________________________________
  29.  
  30. Examine the file named PROTYPE1.CPP for our      ================
  31. first look at a prototype and an illustration of   PROTYPE1.CPP
  32. how it is used.  The prototyping used in C++ is  ================
  33. no different than that used in ANSI-C.
  34. Actually, many C programmers take a rather dim
  35. view of prototyping and seem reluctant to use it, but with C++ it
  36. is considerably more important and is in much heavier use.  In
  37. fact, prototyping is required to be used in some situations in C++.
  38.  
  39. A prototype is a limited model of a more complete entity to come
  40. later.  In this case, the full function is the complete entity to
  41. come later and the prototype is illustrated in line 4.  The
  42. prototype gives a model of the interface to the function that can
  43. be used to check the calls to the function for the proper number
  44. of parameters and the correct types of parameters.  Each call to
  45. the function named do_stuff() must have exactly three parameters
  46. or the compiler will give an error message.  In addition to the
  47. correct number of parameters, the types must be compatible or the
  48. compiler will issue an error message.  Notice that when the
  49. compiler is working on lines 12 and 13, the type checking can be
  50. done based on the prototype in line 4 even though the function
  51. itself is not yet defined.  If the prototype is not given, the
  52. number of parameters will not be checked, nor will the types of the
  53. parameters be checked.  Even if you have the wrong number of
  54. parameters, you will get an apparently good compile and link, but
  55. the program may do some very strange things when it is executed.
  56.  
  57.  
  58.                                                          Page 4-1
  59.  
  60.                                             Chapter 4 - Functions
  61.  
  62.  
  63. To write the prototype, simply copy the header from the function
  64. to the beginning of the program and append a semicolon to the end
  65. as a signal to the compiler that this is not a function but a
  66. prototype.  The variable names given in the prototype are optional
  67. and act merely as comments to the program reader since they are
  68. completely ignored by the compiler.  You could replace the variable
  69. name wings in line 4 with your first name and there would be no
  70. difference in compilation.  Of course, the next person that had to
  71. read your program would be somewhat baffled with your choice of
  72. variable names.
  73.  
  74. In this case, the two function calls to this function, given in
  75. lines 12 and 13, are correct so no error will be listed during
  76. compilation.
  77.  
  78. Even though we wish to use the char type for eyes in the function,
  79. we wish to use it as a number rather than as a character.  The cast
  80. to int in line 20 is required to force the printout of the
  81. numerical value rather than an ASCII character.  The next example
  82. program is similar but without the cast to int.
  83.  
  84.  
  85.  
  86. COMPATIBLE TYPES
  87. _________________________________________________________________
  88.  
  89. We mentioned compatible types earlier so we should review them just
  90. a bit in order to make our discussion of prototyping complete.
  91. Compatible types are any simple types that can be converted from
  92. one to another in a meaningful way.  For example, if you used an
  93. integer as the actual parameter and the function was expecting a
  94. float type as the formal parameter, the system would do the
  95. conversion automatically, without mentioning it to you.  This is
  96. also true of a float changing to a char, or a char changing to an
  97. int.  There are definite conversion rules which would be followed.
  98. These rules are given in great detail in section 3.2 of the draft
  99. of the ANSI-C standard and are also given on page 198 of the second
  100. edition of the K&R reference.
  101.  
  102. If we supplied a pointer to an integer as the actual parameter and
  103. expected an integer as the formal parameter in the function, the
  104. conversion would not be made because they are two entirely
  105. different kinds of values.  Likewise, a structure would not be
  106. converted automatically to a long float, an array, or even to a
  107. different kind of structure, they are all incompatible and cannot
  108. be converted in any meaningful manner.  The entire issue of type
  109. compatibility as discussed in chapter 2 of this tutorial applies
  110. equally well to the compatibility of types when calling a function.
  111. Likewise, the type specified as the return type, in this case void,
  112. must be compatible with the expected return type in the calling
  113. statement, or the compiler will issue a warning.
  114.  
  115.  
  116.  
  117.                                                          Page 4-2
  118.  
  119.                                             Chapter 2 - Functions
  120.  
  121.  
  122. HOW DOES PROTOTYPING WORK?
  123. _________________________________________________________________
  124.  
  125. This is your chance to try prototyping for yourself and see how
  126. well it works and what kinds of error messages you get when you do
  127. certain wrong things.  Change the actual parameters in line 12 to
  128. read (12.2, 13, 12345) and see what the compiler says about that
  129. change.  It will probably say nothing because they are all type
  130. compatible.  If you change it to read (12.0, 13), it will issue a
  131. warning or error because there are not enough arguments given.
  132. Likewise you should receive an error message if you change one of
  133. the parameters in line 13 to an address by putting an ampersand in
  134. front of one of the variable names.  Finally, change the first word
  135. in line 4 from void to int and see what kind of error message is
  136. given.  You will first be required to make the function header in
  137. line 16 agree with the prototype, then you will find that there is
  138. not a variable returned from the function.  You should have a good
  139. feeling that prototyping is doing something good for you after
  140. making these changes.
  141.  
  142. Be sure to compile and execute this program then make the changes
  143. recommended above, attempting to compile it after each change.
  144.  
  145.  
  146.  
  147. A LITTLE MORE PROTOTYPING
  148. _________________________________________________________________
  149.  
  150. Examine the next example program named           ================
  151. PROTYPE2.CPP for a little more information on      PROTYPE2.CPP
  152. prototyping.  This program is identical to the   ================
  153. last one except for a few small changes.  The
  154. variable names have been omitted from the
  155. prototype in line 4 merely as an illustration that they are
  156. interpreted as comments by the C++ compiler.  The function header
  157. is formatted differently to allow for a comment alongside each of
  158. the actual parameters.  This should make the function header a
  159. little more self explanatory.  However, you should remember that
  160. comments should not be used to replace careful selection of
  161. variable names.  In this particular case, the comments add
  162. essentially nothing to the clarity of the program.
  163.  
  164.  
  165.  
  166. WHAT DOES PROTOTYPING COST?
  167. _________________________________________________________________
  168.  
  169. Prototyping is essentially free because it costs absolutely nothing
  170. concerning the run time size or speed of execution.  Prototyping
  171. is a compile time check and slows down the compile time a
  172. negligible amount because of the extra checking that the compiler
  173. must do.  If prototyping finds one error for you that you would
  174. have had to find with a debugger, it has more than paid for itself
  175.  
  176.                                                          Page 4-3
  177.  
  178.                                             Chapter 4 - Functions
  179.  
  180. for use in an entire project.  I once spent 12 hours of debugging
  181. time to find that I forgot to pass the address of a variable to a
  182. function.  Prototyping would have found the error on the first
  183. compilation of this 2000 line program.
  184.  
  185. The only price you pay to use prototyping is the extra size of the
  186. source files because of the prototypes, and the extra time for the
  187. compiler to read the prototypes during the compilation process, but
  188. both costs are negligible.
  189.  
  190. Be sure to compile and execute this example program.  You will find
  191. that it is identical to the last example program.
  192.  
  193.  
  194. PASS BY REFERENCE
  195. _________________________________________________________________
  196.  
  197. Examine The file named PASSREF.CPP for an         ===============
  198. example of a pass by reference, a construct         PASSREF.CPP
  199. which is not available in ANSI-C.  The reference  ===============
  200. variable was mentioned in chapter 1 and it was
  201. recommended there that you don't use it in the
  202. manner illustrated there.  This example program illustrates a
  203. situation where it can be used to your advantage.  The pass by
  204. reference allows the passing of a variable to a function and
  205. returning the changes made in the function to the main program.
  206. In ANSI-C the same effect can be seen when a pointer to a variable
  207. is passed to a function, but use of a reference variable is a
  208. little cleaner.
  209.  
  210. Observe the prototype in line 4 where the second variable has an
  211. ampersand in front of the variable name.  The ampersand instructs
  212. the compiler to treat this variable just like it were passed a
  213. pointer to the variable since the actual variable from the main
  214. program will be used in the function.  In the function itself, in
  215. lines 21 through 24, the variable in2 is used just like any other
  216. variable but we are using the variable passed to this function from
  217. the main program not a copy of it.  The other variable named in1
  218. is treated just like any other normal variable in ANSI-C.  In
  219. effect, the name in2 is a synonym for the variable named index in
  220. the main program.
  221.  
  222. If you prefer to omit the variable names in the prototypes, you
  223. would write the prototype as follows;
  224.  
  225.    void fiddle(int, int&);
  226.  
  227. If you are a Pascal programmer, you will recognize that the
  228. variable named in1 is treated just like a normal parameter in a
  229. Pascal call, a call by value.  The variable named in2 however, is
  230. treated like a variable with the reserved word VAR used in front
  231. of it usually referred to as a call by reference.  The reference
  232. variable is actually a self dereferencing pointer which refers to,
  233. or points to, the original value.
  234.  
  235.                                                          Page 4-4
  236.  
  237.                                             Chapter 4 - Functions
  238.  
  239. When you compile and execute this program, you will find that the
  240. first variable got changed in the function but was returned to its
  241. original value when we returned to the main program.  The second
  242. variable however, was changed in the function and the new value was
  243. reflected back into the variable in the main program which we can
  244. see when the values are listed on the monitor.
  245.  
  246.  
  247. DEFAULT PARAMETERS
  248. _________________________________________________________________
  249.  
  250. Examine the file named DEFAULT.CPP for an         ===============
  251. example of the use of default parameters in C++.    DEFAULT.CPP
  252. This program really looks strange since it        ===============
  253. contains default values for some of the
  254. parameters in the prototype, but these default
  255. values are very useful as we will see shortly.
  256.  
  257. This prototype says that the first parameter named length must be
  258. given for each call of this function because a default value is not
  259. supplied.  The second parameter named width, however, is not
  260. required to be specified for each call, and if it is not specified,
  261. the value 2 will be used for the variable width within the
  262. function.  Likewise, the third parameter is optional, and if it is
  263. not specified, the value of 3 will be used for height within the
  264. function.
  265.  
  266. In line 11 of this program, all three parameters are specified so
  267. there is nothing unusual about this call from any other function
  268. call we have made.  Only two values are specified in line 12
  269. however, so we will use the default value for the third parameter
  270. and the system acts as if we called it with get_value(x, y, 3)
  271. since the default value for the third value is 3.  In line 13, we
  272. only specified one parameter which will be used for the first
  273. formal parameter, and the other two will be defaulted.  The system
  274. will act as if we had called the function with get_volume(x, 2, 3).
  275. Note that the output from these three lines is reversed.  This will
  276. be explained shortly.
  277.  
  278. There are a few rules which should be obvious but will be stated
  279. anyway.  Once a parameter is given a default value in the list of
  280. formal parameters, all of the remaining must have default values
  281. also.  It is not possible to leave a hole in the middle of the
  282. list, only the trailing values can be defaulted.  Of course, the
  283. defaulted values must be of the correct types or a compiler error
  284. will be issued.  The default values can be given in either the
  285. prototype or the function header, but not in both.  If they are
  286. given in both places, the compiler must not only use the default
  287. value, but it must carefully check to see that both values are
  288. identical.  This could further complicate an already very
  289. complicated problem, that of writing a C++ compiler.
  290.  
  291. As a matter of style, it is highly recommended that the default
  292. values be given in the prototype rather than in the function.  The
  293.  
  294.                                                          Page 4-5
  295.  
  296.                                             Chapter 4 - Functions
  297.  
  298. reason will be obvious when we begin using object oriented
  299. programming techniques.
  300.  
  301.  
  302. WHY IS THE OUTPUT SCRAMBLED?
  303. _________________________________________________________________
  304.  
  305. When the compiler finds a cout statement, the complete line of code
  306. is initially scanned from right to left to evaluate any functions,
  307. then the data is output field by field from left to right.
  308. Therefore in line 11, get_value() is evaluated with its internal
  309. output displayed first.  Then the fields of the cout are displayed
  310. from left to right with "Some box data is" displayed next.
  311. Finally, the result of the return from get_value() is output in int
  312. format, the type of the returned value.  The end result is that the
  313. output is not in the expected order when lines 11 through 13 are
  314. executed.  (The output is not what you would intuitively expect to
  315. happen so appears to be a deficiency in the language.  A call to
  316. Borland International, the writers of Turbo C++ and Borland C++,
  317. verified that this is operating correctly.)
  318.  
  319. Lines 15 through 18 are similar to any two of the lines of code in
  320. lines 11 through 13, but are each separated into two lines so the
  321. output is in the expected order.
  322.  
  323. Be sure to compile and execute DEFAULT.CPP after you understand it.
  324. Note that the funny output order will appear again later in this
  325. tutorial.
  326.  
  327.  
  328. VARIABLE NUMBER OF ARGUMENTS
  329. _________________________________________________________________
  330.  
  331. Examine the program named VARARGS.CPP for an      ===============
  332. illustration of the use of a variable number of     VARARGS.CPP
  333. arguments in a function call.                     ===============
  334.  
  335. We have gone to a lot of trouble to get the
  336. compiler to help us by carefully checking how many parameters we
  337. use in the function calls and checking the types of the parameters.
  338. On rare occasion, we may wish to write a function that uses a
  339. variable number of parameters.  The printf() function is a good
  340. example of this.  ANSI-C has a series of three macros available in
  341. the "stdarg.h" header file to allow the use of a variable number
  342. of arguments.  These are available for use with C++ also, but we
  343. need a way to eliminate the strong type checking that is done with
  344. all C++ functions.  The three dots illustrated in line 6 will do
  345. this for us.  This prototype says that a single argument of type
  346. int is required as the first parameter, then no further type
  347. checking will be done by the compiler.
  348.  
  349. You will note that the main program consists of three calls to the
  350. function, each with a different number of parameters, and the
  351. system does not balk at the differences in the function calls.  In
  352.  
  353.                                                          Page 4-6
  354.  
  355.                                             Chapter 4 - Functions
  356.  
  357. fact, you could put as many different types as you desire in the
  358. calls.  As long as the first one is an int type variable, the
  359. system will do its best to compile and run it for you.  Of course
  360. the compiler is ignoring all type checking beyond the first
  361. parameter so it is up to you to make sure you use the correct
  362. parameter types in this call.
  363.  
  364. In this case the first parameter gives the system the number of
  365. additional parameters to look for and handle.  In this simple
  366. program, we simply display the numbers on the monitor to illustrate
  367. that they really did get handled properly.
  368.  
  369. Of course, you realize that using a variable number of arguments
  370. in a function call can lead to very obscure code and should be used
  371. very little in a production program, but the capability exists if
  372. you need it.  Be sure to compile and execute this program.
  373.  
  374.  
  375. FUNCTION NAME OVERLOADING
  376. _________________________________________________________________
  377.  
  378. Examine the file named OVERLOAD.CPP for an       ================
  379. example of a program with the function names       OVERLOAD.CPP
  380. overloaded.  This is not possible in ANSI-C, but ================
  381. is perfectly legal and in fact used quite
  382. regularly in C++.  At first this will seem a bit
  383. strange, but it is one of the keystones of object oriented
  384. programming.  You will see its utility and purpose very clearly in
  385. later chapters of this tutorial.
  386.  
  387. You will notice in this example program that there are three
  388. functions, in addition to the main function, and all three have the
  389. same name.  Your first question is likely to be, "Which function
  390. do you call when you call do_stuff()?"  That is a valid question
  391. and the answer is, the function that has the correct number of
  392. formal parameters of the correct types.  If do_stuff() is called
  393. with an integer value or variable as its actual parameter, the
  394. function beginning in line 23 will be called and executed.  If the
  395. single actual parameter is of type float, the function beginning
  396. in line 28 will be called, and if two floats are specified, the
  397. function beginning in line 34 will be called.
  398.  
  399. It should be noted that the return type is not used to determine
  400. which function will be called.  Only the formal parameters are used
  401. to determine which overloaded function will be called.
  402.  
  403.  
  404. The keyword overload used in line 4 tells the system that you
  405. really do intend to overload the name do_stuff, and the overloading
  406. is not merely an oversight.  This is only required in C++ version
  407. 1.2.  C++ version 2.0 and greater do not require the keyword
  408. overload but allows it to be used optionally in order to allow the
  409. existing body of C++ code to be compatible with newer compilers.
  410. It is not necessary to use this keyword because, when overloading
  411.  
  412.                                                          Page 4-7
  413.  
  414.                                             Chapter 4 - Functions
  415.  
  416. is used in C++, it is generally used in a context in which it is
  417. obvious that the function name is overloaded.
  418.  
  419. The actual selection of which function to actually call is done at
  420. compile time, not at execution time so the program is not slowed
  421. down.  If each of the overloaded function names were changed to
  422. different names, each being unique, there would be no difference
  423. in execution size or speed of the resulting program.
  424.  
  425. Overloading of function names may seem very strange to you, and it
  426. is strange if you are used to the rules of K&R or ANSI-C
  427. programming.  As you gain experience with C++, you will feel very
  428. comfortable with this and you will use it a lot in your C++
  429. programming.
  430.  
  431. Note the use of the keyword const used in some of the function
  432. prototypes and headers.  Once again, this prevents the programmer
  433. from accidentally changing the formal parameter within the
  434. function.  In a function as short as these, there is no real
  435. problem with an accidental assignment.  In a real function that you
  436. occasionally modify, you could easily forget the original intention
  437. of the use of a value and attempt to change it during an extended
  438. debugging session.
  439.  
  440.  
  441. PROGRAMMING EXERCISES
  442. _________________________________________________________________
  443.  
  444.  
  445. 1.   Change the type of wings in the prototype of PROTYPE1.CPP to
  446.      float so that it disagrees with the function definition to see
  447.      if you get a compilation error.
  448.  
  449. 2.   Change the function definition in PROTYPE1.CPP to agree with
  450.      the changed prototype.  Compile and execute the program
  451.      without changing the calls in lines 12 and 13.  Explain the
  452.      results.
  453.  
  454. 3.   In DEFAULT.CPP, remove the default value from the prototype
  455.      for height only to see what kind of compiler error you get.
  456.      Only the last values of the list can be defaulted.
  457.  
  458. 4.   In OVERLOAD.CPP, change the names of the three functions so
  459.      that each is a unique name and compare the size of the
  460.      resulting executable file with that given for the present
  461.      program.
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469.  
  470.  
  471.                                                          Page 4-8
  472.